<?php

/**
 * Created by PhpStorm.
 * User: yf
 * Date: 2017/12/29
 * Time: 下午7:26
 */
namespace App\System\Http\AbstractInterface;

use App\System\Http\Message\Status;
use App\System\Http\Request;
use App\System\Http\Response;
use App\System\Component\View\TwigView;
use App\System\Component\Di;

abstract class Controller
{

    private $actionName;

    private $request;

    private $response;

    abstract function index();

    public function __construct(string $actionName, Request $request, Response $response)
    {
        $this->request = $request;
        $this->response = $response;
        $this->actionName = $actionName;
        if ($actionName == '__hook') {
            $this->response()->withStatus(Status::CODE_BAD_REQUEST);
        } else {
            $this->__hook($actionName);
        }
    }

    protected function actionNotFound($action): void
    {
        $this->response()->withStatus(Status::CODE_NOT_FOUND);
    }

    protected function afterAction($actionName): void
    {}

    protected function onException(\Throwable $throwable, $actionName): void
    {
        throw $throwable;
    }

    protected function onRequest($action): ?bool
    {
        return true;
    }

    protected function getActionName(): string
    {
        return $this->actionName;
    }

    protected function resetAction(string $action): void
    {
        $this->actionName = $action;
    }

    protected function __hook(?string $actionName): void
    {
        if ($this->onRequest($actionName) !== false) {
            $actionName = $this->actionName;
            // 支持在子类控制器中以private，protected来修饰某个方法不可见
            $ref = new \ReflectionClass(static::class);
            if ($ref->hasMethod($actionName) && $ref->getMethod($actionName)->isPublic()) {
                try {
                    $this->$actionName(); // 这里面会重复执行
                    $this->afterAction($actionName);
                } catch (\Throwable $exception) {
                    $this->onException($exception, $actionName);
                }
            } else {
                throw new \Exception(static::class . "中没有找到" . $actionName);
            }
        } else {
            throw new \Exception("没有权限访问" . $actionName);
        }
    }

    protected function request(): Request
    {
        return $this->request;
    }

    protected function response(): Response
    {
        return $this->response;
    }

    protected function writeJson($statusCode = 200, $result = null, $msg = null)
    {
        $data = Array(
            "code" => $statusCode,
            "result" => $result,
            "msg" => $msg
        );
        $this->response()->write(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        $this->response()->withHeader('Content-type', 'application/json;charset=utf-8');
        $this->response()->withStatus($statusCode);
    }

    protected function twig(): TwigView
    {
        return Di::getInstance()->get('twig');
    }

    /**
     * * 浏览器友好的变量输出 * @param mixed $var 变量 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 * @param string $label 标签 默认为空 * @param boolean $strict 是否严谨 默认为true * @return void|string
     */
    /**
     * 浏览器友好的变量输出
     *
     * @param mixed $var
     *            变量
     * @param boolean $echo
     *            是否输出 默认为True 如果为false 则返回输出字符串
     * @param string $label
     *            标签 默认为空
     * @param boolean $strict
     *            是否严谨 默认为true
     * @return void|string
     */
    protected function getNameSpace()
    {
        return self::class;
    }

    function __destruct()
    {
        $this->response->response();
    }
}